package com.eastfair.venueservice.service.impl;

import cn.hutool.core.bean.BeanUtil;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.annotation.annotation.cache.Cache;
import com.eastfair.annotation.annotation.cache.Magic;
import com.eastfair.auth.api.AuthServiceFeign;
import com.eastfair.auth.api.UserAccountServiceFeign;
import com.eastfair.auth.dto.UserAccountDto;
import com.eastfair.auth.vo.OrganizationVo;
import com.eastfair.auth.vo.UserAccountVo;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.projectcore.enumeration.DataIsolationSystemSceneEnum;
import com.eastfair.venueservice.dao.ServiceInventoryInFlowMapper;
import com.eastfair.venueservice.dto.ExhibitionManageQuery;
import com.eastfair.venueservice.dto.ServiceInventoryInFlowDTO;
import com.eastfair.venueservice.dto.ServiceInventoryInFlowQuery;
import com.eastfair.venueservice.entity.ServiceInventory;
import com.eastfair.venueservice.entity.ServiceInventoryInFlow;
import com.eastfair.venueservice.entity.ServiceItem;
import com.eastfair.venueservice.enumeration.ServiceBorrowReturnGoodsLossStateEnum;
import com.eastfair.venueservice.enumeration.ServiceInventoryInFlowInStockTypeEnum;
import com.eastfair.venueservice.exceptioncode.VenueServiceExceptionCode;
import com.eastfair.venueservice.service.*;
import com.eastfair.venueservice.vo.ExhibitionManageVO;
import com.eastfair.venueservice.vo.ServiceInventoryInFlowVO;
import com.eastfair.venueservice.vo.ServiceProviderVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
* <p>
    * 业务实现类
    * 服务库存入库流水记录
    * </p>
*
* @author linan
* @date 2022-09-19
*/
@Slf4j
@Service
//@DS("#thread.tenant")
public class ServiceInventoryInFlowServiceImpl extends SuperServiceImpl<ServiceInventoryInFlowMapper, ServiceInventoryInFlow> implements ServiceInventoryInFlowService {

    public static final int VAL_99999999 = 99999999;
    @Resource
    private ServiceInventoryService serviceInventoryService;

    @Resource
    private UserAccountServiceFeign userAccountServiceFeign;

    @Resource
    private AuthServiceFeign authServiceFeign;

    @Resource
    private ServiceProviderService serviceProviderService;

    @Resource
    private ExhibitionManageService exhibitionManageService;

    @Resource
    private ServiceLossService serviceLossService;

    @Resource
    private ServiceItemService serviceItemService;
    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
    */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<ServiceInventoryInFlow> modelList) {
    modelList.stream().forEach(s -> {
    s.setIsDeleted(BusinessConstant.YES);
    });
    // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
    return R.successDef();
    }



    @Override
    protected R<Boolean> handlerSave(ServiceInventoryInFlow model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        return R.successDef();
    }

    /**
    * 通用查询
    *
    * @param modelDTO DTO
    * @param ids 主键id集合
    * @return list
    */
    @Override
    public List<ServiceInventoryInFlow> list(ServiceInventoryInFlowDTO modelDTO, List<Long> ids) {
        return ((ServiceInventoryInFlowService) AopContext.currentProxy()).listOfCache(modelDTO, ids);
    }


    /**
     * 缓存查询
     *
     * @param modelDTO DTO
     * @param ids 主键id集合
     * @return list
     */
    @Override
    @Cache(key = "",
       magic = @Magic(
       key = "{"+
       "{'isEnabled', #args[0]?.isEnabled},"+
       "{'inventoryId', #args[0]?.inventoryId},"+
       "{'inventoryCode', #args[0]?.inventoryCode},"+
       "{'beforeInventoryNum', #args[0]?.beforeInventoryNum},"+
       "{'afterInventoryNum', #args[0]?.afterInventoryNum},"+
       "{'inNum', #args[0]?.inNum},"+
       "{'inStockType', #args[0]?.inStockType},"+
        "{'id', #args[1]}"+
        "}"))
    public List<ServiceInventoryInFlow> listOfCache(ServiceInventoryInFlowDTO modelDTO, List<Long> ids) {
       //查询
       QueryWrapper<ServiceInventoryInFlow> queryWrapper = new QueryWrapper<>();
       if (modelDTO != null) {
                    queryWrapper.lambda().eq(StringUtils.isNotBlank(modelDTO.getInventoryCode()),ServiceInventoryInFlow::getInventoryCode,modelDTO.getInventoryCode());
                    queryWrapper.lambda().eq(modelDTO.getBeforeInventoryNum() != null,ServiceInventoryInFlow::getBeforeInventoryNum,modelDTO.getBeforeInventoryNum());
                    queryWrapper.lambda().eq(modelDTO.getAfterInventoryNum() != null,ServiceInventoryInFlow::getAfterInventoryNum,modelDTO.getAfterInventoryNum());
                    queryWrapper.lambda().eq(modelDTO.getInNum() != null,ServiceInventoryInFlow::getInNum,modelDTO.getInNum());
                    queryWrapper.lambda().eq(Objects.nonNull(modelDTO.getInStockType()),ServiceInventoryInFlow::getInStockType,modelDTO.getInStockType());
            }
            if (ids != null && !ids.isEmpty()) {
            queryWrapper.lambda().in(ServiceInventoryInFlow::getId, ids);
            }
            queryWrapper.lambda().eq(ServiceInventoryInFlow::getIsDeleted, BusinessConstant.DELETE_NO);
            List<ServiceInventoryInFlow> modelList = list(queryWrapper);
            return modelList;
    }

    public static void main(String[] args) {
        System.out.println(BigDecimal.valueOf(VAL_99999999).compareTo(BigDecimal.valueOf(VAL_99999999))>0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveInFlow(ServiceInventoryInFlowDTO serviceInventoryInFlowDTO) {
        // 入库报损
        if (Objects.nonNull(serviceInventoryInFlowDTO.getGoodsLossState()) && !ServiceBorrowReturnGoodsLossStateEnum.UNDAMAGED.eq(serviceInventoryInFlowDTO.getGoodsLossState())) {
            return serviceLossService.inventoryInFlowLoss(serviceInventoryInFlowDTO);
        }
        // 查询原库存数量
        ServiceInventory serviceInventory = serviceInventoryService.getOne(new QueryWrapper<ServiceInventory>().lambda()
                .eq(ServiceInventory::getInventoryCode, serviceInventoryInFlowDTO.getInventoryCode()).eq(ServiceInventory::getIsDeleted, BusinessConstant.NO));
        if(Objects.isNull(serviceInventory)){
            return true;
        }else if(!serviceInventoryInFlowDTO.getInStockType().eq(ServiceInventoryInFlowInStockTypeEnum.INIT) && serviceInventory.getInventoryNum().add(serviceInventoryInFlowDTO.getInNum()).compareTo(BigDecimal.valueOf(VAL_99999999))>0){
            throw BizException.wrap(VenueServiceExceptionCode.INVENTORY_NUM_MORE_THAN_99999999);
        }
        // 查询库存所属展会
        Long serviceItemId = serviceInventory.getServiceItemId();
        ServiceItem serviceItem = serviceItemService.getById(serviceItemId);
        if (Objects.nonNull(serviceItem) && Objects.isNull(serviceInventoryInFlowDTO.getExhibitionManageId())) {
            serviceInventoryInFlowDTO.setExhibitionManageId(serviceItem.getExhibitionManageId());
        }
        // 封装要插入的流水数据
        ServiceInventoryInFlow  serviceInventoryInFlow= BeanUtil.copyProperties(serviceInventoryInFlowDTO,ServiceInventoryInFlow.class);
        if(serviceInventoryInFlowDTO.getInStockType().eq(ServiceInventoryInFlowInStockTypeEnum.INIT)){
            serviceInventoryInFlow.setBeforeInventoryNum(BigDecimal.ZERO);
            serviceInventoryInFlow.setAfterInventoryNum(serviceInventoryInFlowDTO.getInNum());
        }else {
            serviceInventoryInFlow.setBeforeInventoryNum(serviceInventory.getInventoryNum());
            serviceInventoryInFlow.setAfterInventoryNum(serviceInventory.getInventoryNum().add(serviceInventoryInFlowDTO.getInNum()));
        }
        boolean flag = save(serviceInventoryInFlow);
        // 变更库存(初始化不变库存，但写库存记录)
        if (!ServiceInventoryInFlowInStockTypeEnum.INIT.eq(serviceInventoryInFlow.getInStockType())) {
            serviceInventoryService.addInventory(serviceInventoryInFlowDTO.getInventoryCode(), serviceInventoryInFlowDTO.getInNum());
        }
        return flag;
    }

    @Override
    public Page<ServiceInventoryInFlowVO> queryInFlowList(PageParams<ServiceInventoryInFlowQuery> serviceInventoryInFlowQuery) {
        serviceInventoryInFlowQuery.setSort(null);
        serviceInventoryInFlowQuery.setOrder(null);
        Page<ServiceInventoryInFlowQuery> serviceInventoryInFlowQueryPage=serviceInventoryInFlowQuery.buildPage();
        ServiceInventoryInFlowQuery model = serviceInventoryInFlowQuery.getModel();
        String serviceProviderType = model.getServiceProviderType();
        QueryWrapper<ServiceInventory> wrapper = new QueryWrapper<>();
        wrapper.eq("inf.is_deleted",BusinessConstant.NO)
                .eq("inf.is_enabled",BusinessConstant.YES)
                .like(Strings.isNotBlank(model.getServiceName()),"b.service_name",model.getServiceName())
                .eq(Objects.nonNull(model.getServiceCategoryId()),"a.service_category_id",model.getServiceCategoryId())
                .eq(Objects.nonNull(model.getInStockType()),"inf.in_stock_type",model.getInStockType())
                .ge(Objects.nonNull(model.getCreateTimeStart()), "inf.create_time", model.getCreateTimeStart())
                .le(Objects.nonNull(model.getCreateTimeEnd()), "inf.create_time", model.getCreateTimeEnd())
                .eq(Objects.nonNull(model.getServiceProviderType()), "b.service_provider_type", model.getServiceProviderType())
                .eq(Objects.nonNull(model.getServiceProviderId()), "b.service_provider_id", model.getServiceProviderId())
                .eq(Objects.nonNull(model.getExhibitionManageId()), "inf.exhibition_manage_id", model.getExhibitionManageId())
                .orderByDesc("inf.create_time");
        if(Strings.isBlank(serviceProviderType)){
            // 场馆查询
            String keyword = StringUtils.isNotBlank(model.getKeyword()) ? model.getKeyword() : Strings.EMPTY;
            // 查询所有部门
            List<OrganizationVo> data = authServiceFeign.queryList(Collections.emptyList()).getData();
            Map<Long, String> orgMap = data.stream().filter(e -> e.getName().contains(keyword)).collect(Collectors.toMap(OrganizationVo::getId, OrganizationVo::getName));
            Set<Long> orgIds = orgMap.keySet();
            // 查询所有服务商
            List<ServiceProviderVO> serviceProviderVOS = serviceProviderService.listServiceProviderByIds(Collections.emptyList());
            Map<Long, String> serviceProviders = serviceProviderVOS.stream().filter(e -> e.getCompanyName().contains(keyword)).collect(Collectors.toMap(ServiceProviderVO::getId, ServiceProviderVO::getCompanyName));
            Set<Long> providers =serviceProviders.keySet();
            // 查询所有展会
            R<List<ExhibitionManageVO>> allExhibitionManage = exhibitionManageService.queryAllExhibitionManage(ExhibitionManageQuery.builder().build());
            Map<Long, String> exhibitionMap = allExhibitionManage.getData().stream().filter(e -> e.getExhibitionName().contains(keyword)).collect(Collectors.toMap(ExhibitionManageVO::getId, ExhibitionManageVO::getExhibitionName));
            Set<Long> exhibitionManageIds = exhibitionMap.keySet();
            wrapper.eq("b.service_provider_type", DataIsolationSystemSceneEnum.P_COMPOSITE_VENUE.getCode());
            if(StringUtils.isNotBlank(keyword)){
                wrapper.and(e->e.or(f->f.like(StringUtils.isNotBlank(keyword) ,"b.service_name",model.getKeyword()))
                        .or(StringUtils.isNotBlank(keyword) && CollectionUtils.isNotEmpty(orgIds),f->f.in("b.service_provider_id",orgIds))
                        .or(StringUtils.isNotBlank(keyword) && CollectionUtils.isNotEmpty(providers),f->f.in("b.service_provider_id",providers))
                        .or(StringUtils.isNotBlank(keyword) && CollectionUtils.isNotEmpty(exhibitionManageIds),f->f.in("inf.exhibition_manage_id",exhibitionManageIds)));
            }
            Page<ServiceInventoryInFlowVO> serviceInventoryInFlowVOPage = baseMapper.queryInFlowList(serviceInventoryInFlowQueryPage, wrapper);
            List<Long> userIds = serviceInventoryInFlowVOPage.getRecords().stream().map(ServiceInventoryInFlowVO::getCreatedBy).collect(Collectors.toList());
            UserAccountDto userAccountDto = new UserAccountDto();
            userAccountDto.setUserIds(userIds);
            //获取人员信息
            R<List<UserAccountVo>> listR = userAccountServiceFeign.querySimpleByIds(userAccountDto);
            //把人员信息转成map
            Map<Long, UserAccountVo> userMap = listR.getData().stream().collect(Collectors.toMap(UserAccountVo::getId, Function.identity()));
            for (ServiceInventoryInFlowVO record : serviceInventoryInFlowVOPage.getRecords()) {
                record.setCreatedName(Objects.nonNull(userMap.get(record.getCreatedBy()))? userMap.get(record.getCreatedBy()).getRealName():Strings.EMPTY);
                record.setServiceProviderName(Strings.isNotBlank(orgMap.get(record.getServiceProviderId()))? orgMap.get(record.getServiceProviderId()):serviceProviders.get(record.getServiceProviderId()));
                record.setExhibitionManageName(exhibitionMap.get(record.getExhibitionManageId()));
            }
            return serviceInventoryInFlowVOPage;
        }
        // 主场处理
        wrapper.eq("b.service_provider_type", DataIsolationSystemSceneEnum.P_COMPOSITE_COURT.getCode());
        Page<ServiceInventoryInFlowVO> resultPage = baseMapper.queryInFlowList(serviceInventoryInFlowQueryPage, wrapper);
        List<Long> userIds = resultPage.getRecords().stream().map(ServiceInventoryInFlowVO::getCreatedBy).collect(Collectors.toList());
        UserAccountDto userAccountDto = new UserAccountDto();
        userAccountDto.setUserIds(userIds);
        //获取人员信息
        R<List<UserAccountVo>> listR = userAccountServiceFeign.querySimpleByIds(userAccountDto);
        //把人员信息转成map
        if(Objects.nonNull(listR) && CollectionUtils.isNotEmpty(listR.getData())){
            Map<Long, UserAccountVo> userMap = listR.getData().stream().collect(Collectors.toMap(UserAccountVo::getId, Function.identity()));
            //获取分类下服务项数量
            if (Objects.nonNull(resultPage.getRecords()) && resultPage.getRecords().size()>0) {
                resultPage.getRecords().forEach((s)->{
                    s.setCreatedName(Objects.nonNull(userMap.get(s.getCreatedBy()))? userMap.get(s.getCreatedBy()).getRealName():Strings.EMPTY);
                });
            }
        }
        return resultPage;
    }


    /**
     * do转vo
     * @param model model
     * @return modelVo
     */
    @Override
    public ServiceInventoryInFlowVO doToVo(ServiceInventoryInFlow model) {
        ServiceInventoryInFlowVO modelVo = new ServiceInventoryInFlowVO();
        BeanUtils.copyProperties(model, modelVo);
        modelVo.setId(model.getId());
        return modelVo;
    }
    /**
     * do转vo
     * @param modelList modelList
     * @return list
     */
     @Override
     public List<ServiceInventoryInFlowVO> doToVos(List<ServiceInventoryInFlow> modelList) {
        if (modelList == null || modelList.isEmpty()) {
        return null;
        }
        List<ServiceInventoryInFlowVO> result = new ArrayList<>();
        for (ServiceInventoryInFlow model : modelList) {
           result.add(doToVo(model));
        }
        return result;
    }

}
